package com.hx.mypetstore.network;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;

import org.json.JSONObject;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class OkHttp {
    private static int METHOD = 1000;
    private static final int POST = 1001;
    private static final int GET = 1002;
    private static OkHttp okHttp;

    public static void instance() {
        okHttp = new OkHttp();
    }

    private static OkHttpClient okHttpClient;
    private static RequestBody requestBody;
    private static Request request;
    private static String requestUrl;

    public static OkHttp post(String url) {
        instance();
        okHttpClient = new OkHttpClient();
        METHOD = POST;
        requestUrl = url;
        return okHttp;
    }

    public static OkHttp get(String url) {
        instance();
        okHttpClient = new OkHttpClient();
        METHOD = GET;
        requestUrl = url;
        return okHttp;
    }

    private Map<String, Object> params = new HashMap();

    public OkHttp add(String key, Object value) {
        params.put(key, String.valueOf(value));
        return this;
    }

    public OkHttp add(Map<String, String> map) {
        params.putAll(map);
        return this;
    }

    private int BUILD_TYPE = 300;
    private final int JSON_TYPE = 301;
    private final int FILE_TYPE = 302;
    private MediaType JSONType = MediaType.parse("application/json; charset=utf-8");

    public <T> void buildByJson(final HttpCallBack<T> httpCallBack) {
        BUILD_TYPE = JSON_TYPE;
        build(httpCallBack);
    }

    public <T> void build(final HttpCallBack<T> httpCallBack) {
        this.httpCallBack = httpCallBack;
        handler.sendEmptyMessage(START);
        switch (BUILD_TYPE) {
            case JSON_TYPE: //json提交
                requestBody = RequestBody.create(JSONType, GsonBinder.toJsonStr(params));
                break;
            case FILE_TYPE:
                break;
            default:
                //form表单提交
                FormBody.Builder builder = new FormBody.Builder();
                for (String key : params.keySet()) {
                    builder.add(key, (String) params.get(key));
                }
                requestBody = builder.build();
                break;
        }
        if (METHOD == GET) {
            request = new Request.Builder()
                    .url(requestUrl)
                    .get()//默认就是GET请求，可以不写
                    .build();
        } else if (METHOD == POST) {
            request = new Request.Builder()
                    .url(requestUrl)
                    .post(requestBody)
                    .build();
        }
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Message message = new Message();
                message.obj = e.getMessage();
                message.what = ERROR;
                handler.sendMessage(message);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    String jsonStr = response.body().string();
                    JSONObject jsonObject = new JSONObject(jsonStr);
                    String msg = "";
                    if (jsonObject.has("info")) {
                        msg = jsonObject.getString("info");
                    }
                    if (jsonObject.has("status")) {
                        String status = jsonObject.getString("status");
                        if ("1".equals(status)) {
                            //成功
                            if (jsonObject.has("data")) {
                                T data = GsonBinder.toObj(jsonObject.getString("data"),httpCallBack.mType);
                                response.close();
                                Message message = new Message();
                                message.obj = data;
                                message.what = SUCCESS;
                                handler.sendMessage(message);
                            }
                        } else if ("0".equals(status)) {
                            //错误
                            Message message = new Message();
                            message.obj = msg;
                            message.what = ERROR;
                            handler.sendMessage(message);
                        } else {
                            Message message = new Message();
                            message.obj = msg;
                            message.what = ERROR;
                            handler.sendMessage(message);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    handler.sendEmptyMessage(END);
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
                handler.sendEmptyMessage(END);
            }
        });
    }
    private HttpCallBack httpCallBack;
    @SuppressLint("HandlerLeak")
    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case START:
                    httpCallBack.start();
                    break;
                case SUCCESS:
                    httpCallBack.success(msg.obj);
                    break;
                case ERROR:
                    if (msg.obj != null) {
                        httpCallBack.error(msg.obj.toString());
                    }
                    httpCallBack.end();
                    break;
                case END:
                    httpCallBack.end();
                    break;
            }
        }
    };
    private final int START = 10001;
    private final int SUCCESS = 10002;
    private final int ERROR = 10003;
    private final int END = 10004;
}
